﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using DemoRealtimeData.Service;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.Charts;
using Microsoft.Research.DynamicDataDisplay.Common;
using Microsoft.Research.DynamicDataDisplay.DataSources;

namespace DemoRealtimeData.ViewModel
{
    internal sealed class Curve
    {
        // ******************************************** //
        #region "static"

        private readonly static Color[] _colors;

        static Curve()
        {
            _colors = new Color[]
            {
                Colors.Blue,
                Colors.Green,
                Colors.Red,
                Colors.Purple,
                Colors.Brown,
                Colors.Magenta,
                Colors.Black,
                Colors.DarkCyan,
                Colors.DarkGoldenrod,
                Colors.Coral,
                Colors.Orange,
                Colors.Olive,
                Colors.Navy,
                Colors.PaleVioletRed
            };
        }

        #endregion

        // ******************************************** //
        #region "member field"

        private string _measkey;
        private Color _color;
        private RingArray<Measurement> _points;
        private LineGraph _linegraph;

        #endregion

        // ******************************************** //
        #region "constructor"

        public Curve(string key, int index)
        {
            _measkey = key;
            _color = _colors[index % _colors.Length];

            _points = new RingArray<Measurement>(300);
        }

        #endregion

        // ******************************************** //
        #region "public API"

        public string Key { get { return _measkey; } }
        public Color Color { get { return _color; } }

        public bool IsVisible
        {
            get { return _linegraph.Visibility == Visibility.Visible; }
            set
            {
                var visibility = value ? Visibility.Visible : Visibility.Collapsed;
                _linegraph.Visibility = visibility;
                _linegraph.Description.LegendItem.Visibility = visibility;
            }
        }

        public IPlotterElement LineGraph
        {
            get { return _linegraph; }
        }

        public void AddMeasurement(Measurement m)
        {
            _points.Add(m);
        }

        public void Initialize(ChartPlotter plotter)
        {
            var ds = new EnumerableDataSource<Measurement>(_points);
            ds.SetXMapping(p => ((HorizontalDateTimeAxis)plotter.HorizontalAxis).ConvertToDouble(p.Time));
            ds.SetYMapping(p => p.Value);
            _linegraph = plotter.AddLineGraph(ds, _color, 2, _measkey);
        }

        #endregion

    }

    public sealed class CurvePresenter
    {
        // -------------------------------------- //
        #region "member fields"

        private readonly IDictionary<string, Curve> _curves;
        private readonly ChartPlotter _plotter;

        #endregion

        // -------------------------------------- //
        #region "constructor"

        public CurvePresenter(IEnumerable<string> keys, ChartPlotter plotter)
        {
            _plotter = plotter;

            _curves = new Dictionary<string, Curve>();
            int index = 0;
            foreach (var key in keys)
            {
                var curve = new Curve(key, index);
                ++index;

                curve.Initialize(plotter);
                _curves.Add(key, curve);
            }
        }

        #endregion

        // -------------------------------------- //
        #region "public API"

        public void OnNewMeasurements(IEnumerable<Measurement> allMeasurements)
        {
            foreach (var m in allMeasurements)
            {
                _curves[m.Key].AddMeasurement(m);
            }

        }

        public void OnSelectionChanged(ISet<string> selectedKeys)
        {
            if (selectedKeys == null) return;
            foreach (var kv in _curves)
            {
                kv.Value.IsVisible = selectedKeys.Contains(kv.Key);
            }
        }

        #endregion
    }
}
